Snowball_233

Snowball_233

A student who is learning coding.

Restore files deleted by rm but occupied by processes.

An extremely unfortunate incident happened last month when I was enthusiastically preparing to write a menu system for my Minecraft server. For some unknown reason, Termius automatically completed what I originally wanted to write as 'cd ./server' to 'rm -rf ./server'. However, I was able to recover more than 95% of the data in the end.


Scope#

  • The file is still running in the cache, which means that during the recovery process, you cannot terminate the process or shut down.

Steps#

  1. Accidentally delete a file, but the file is occupied by a process.

    $ rm test.sh
    
  2. Use the lsof command to list the files that have been deleted but are still occupied by processes.

    $ lsof | grep -i delete | grep speed
    sh  6567  root  4r  REG  253,0  865  /home/test.sh(deleted)
    
    • In the above output, the first item 'sh' is the process name, and the second item '6567' is the process ID.
  3. Enter the process directory.

    $ cd /proc/6567/fd
    $ ls -la
    lr-x------. 1 root root 64 July 13 02:10 4 -> /home/test.sh (deleted)
    
    • In the above output, the ninth item '4' is the file descriptor.
  4. Recovery.

    $ cat 4 > /home/test.sh
    

Recovering a Folder#

  • If a folder is also deleted, manually recovering it can be cumbersome, especially when dealing with numerous small files. In this case, we can use a small program to perform batch recovery.

  • Before proceeding, you need to export all the files that need to be recovered in Step 1 to a log file. We won't go into too much detail here.

    use std::fs;
    use std::io::Read;
    
    fn main() {
        let mut log_file = fs::File::open("/home/deleted_files.log").unwrap(); // Replace with the path to your file list to be recovered
        let mut logs = String::new();
        log_file.read_to_string(&mut logs).unwrap();
        let mut command = String::new();
        let mut paths = Vec::new();
    
        let logs = logs.split("\n");
    
        for log in logs {
            let log = log.split_whitespace().collect::<Vec<&str>>();
    
            if log.len() < 12 {
                continue;
            }
    
            let number = log[8]; // 8 is the column number where the file descriptor is located, modify according to the actual file
            let path = log[10]; // 10 is the column number where the original file path is located, modify according to the actual file
    
            if !path.starts_with("/home") { // Replace with the target folder where you want to recover
                continue;
            }
    
            println!("{}: {}", number, path);
            command.push_str(format!("cat {} > ~/recovery{}\n", number, path).as_str());
    
            let path = path.split("/").collect::<Vec<&str>>();
            let path = path[..path.len() - 1].join("/");
            let path = format!("~/recovery{}", path);
    
            if !paths.contains(&path) {
                paths.push(path);
            }
        }
    
        let mut complete_cmd = String::new();
    
        for path in paths {
            complete_cmd.push_str(format!("mkdir -p {}\n", path).as_str());
        }
    
        println!("{}", complete_cmd);
        complete_cmd.push_str(&command);
    
        fs::write("recovery.sh", complete_cmd).unwrap();
    }
    
  • Finally, run the generated recovery.sh file to recover all the files.


Note: For a Minecraft server, player data cannot be directly recovered, and this method cannot guarantee the recovery of all deleted files. Please remember to regularly backup your files and avoid regretting the consequences of accidental deletion!

This article is synchronized and updated to xLog by Mix Space.
The original link is https://blog.rescueme.life/posts/devops/restore-files-deleted-by-rm-but-occupied-by-processes


Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.